package com.nicolaspigelet.dopplrclient
{
	import aze.motion.easing.Back;
	import aze.motion.eaze;
	import com.dopplr.api.API;
	import com.dopplr.api.City;
	import com.dopplr.api.Model;
	import com.dopplr.api.Traveller;
	import com.dopplr.api.Trip;
	import com.google.maps.LatLng;
	import com.google.maps.Map;
	import com.google.maps.MapEvent;
	import com.google.maps.MapType;
	import com.google.maps.overlays.Marker;
	import com.google.maps.overlays.Polygon;
	import com.google.maps.overlays.PolygonOptions;
	import com.google.maps.styles.FillStyle;
	import com.google.maps.styles.StrokeStyle;
	import com.nicolaspigelet.dopplrclient.data.Bundle;
	import com.nicolaspigelet.dopplrclient.UI.FellowUI;
	import com.nicolaspigelet.dopplrclient.UI.InfoUI;
	import com.nicolaspigelet.dopplrclient.UI.LoaderUI;
	import com.nicolaspigelet.dopplrclient.UI.LoginUI;
	import com.nicolaspigelet.dopplrclient.UI.UserUI;
	import com.nicolaspigelet.maps.CirclePoints;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.DataEvent;
	import flash.events.ErrorEvent;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.StatusEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.utils.Timer;
	import org.flashdevelop.utils.FlashConnect;
	
	/**
	 * ...
	 * @author Nicolas Pigelet aka tanaki
	 */
	public class Main extends Sprite 
	{
		private var __map:Map;
		private var __model:Model;
		private var __homeCity:Marker;
		private var __traveller:Traveller;
		private var __protector:Shape;
		private var __login:Sprite;
		private var __loader:LoaderUI;
		private var __info:InfoUI;
		private var __user:UserUI;
		private var __cityVisited:Array;
		private var __idVisited:Array;
		private var __timerCities:Timer;
		private var __timerFellows:Timer;
		private var __fellows:Array;
		private var __url:String;
		private var __urRequest:URLRequest;
		private var __urLoader:URLLoader;
		private var __aMarkers:Array;
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			stage.addEventListener(Event.RESIZE, __resize);
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			
			__model = new Model();
			
			__map = new Map();
			__map.key = "ABQIAAAAwOJ5S62JvXXj-CNof_dfXBSc4jXVGazDLFjGDDneIOJv2NAY3hTb_h79xzFE-N9zsDHyXlAzlQl7KQ";
			__map.sensor = "true";
			__map.setSize(new Point(stage.stageWidth, stage.stageHeight));
			__map.addEventListener(MapEvent.MAP_READY, __onMapReady);
			addChild(__map);
		}
		
		// initialisation de la map
		private function __onMapReady(e:MapEvent):void 
		{	
			__map.disableDragging();
			__map.setCenter(new LatLng(35, 0), 2, MapType.NORMAL_MAP_TYPE);
			
			__protector = new Shape();
			__protector.graphics.beginFill(0xcccccc);
			__protector.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
			__protector.alpha = 0;
			
			__login = new LoginUI();
			__login.x = (stage.stageWidth - __login.width) >> 1;
			__login.y = - __login.height - 20;
			__login.addEventListener(Event.INIT, __initApp);
			
			__loader = new LoaderUI();
			__loader.x = (stage.stageWidth - __loader.width) >> 1;
			__loader.y = stage.stageHeight + 20;
			
			addChild(__protector);
			addChild(__login);
			addChild(__loader);
			
			eaze(__protector).delay(0.5).to(0.8, { alpha : 0.8 } )
				.chain(__login).to(0.5, { alpha : 1, y : (stage.stageHeight - __login.height) >> 1 } ).easing(Back.easeOut);
		}
		
		// submit form
		private function __initApp(e:DataEvent):void 
		{
			eaze(__login).to(0.5, { y : -__login.height - 20 } ).easing(Back.easeIn).onComplete(__removeLogin)
				.chain(__loader).to(0.5, { y : (stage.stageHeight - __loader.height) >> 1 } ).easing(Back.easeOut)
				.onComplete(__launchLoad, e.text);
		}
		
		// load traveller infos
		private function __launchLoad(nick:String):void
		{
			__url = Bundle.API_URL + "traveller_info?token=" + Bundle.TOKEN + "&traveller=" + nick;
			__urRequest = new URLRequest(__url);
            __urLoader = new URLLoader();
            __urLoader.addEventListener(Event.COMPLETE, __userLoaded);
            __urLoader.addEventListener(IOErrorEvent.IO_ERROR, __errorHandler);
            __urLoader.addEventListener(ProgressEvent.PROGRESS, __progressHandler);
			__urLoader.load(__urRequest);
			
			//__api.loadTravellerInfo(text, __userLoaded);
		}
		
		// traveller infos loaded
		private function __userLoaded( e:Event ):void
		{
			var traveller_info:XML = XML(__urLoader.data);
			if (traveller_info.error[0]) {
				__errorHandler();
			}
			else {
				__traveller = __model.getTravellerfromXML(traveller_info.traveller[0]);
				__user = new UserUI(__traveller);
				__user.x = 20;
				__user.y = -__user.height - 20;
				addChild(__user);
				
				__user.addEventListener(Event.INIT, __loadTrips);
				
				__info = new InfoUI();
				__info.x = stage.stageWidth - __info.width - 20;
				__info.y = stage.stageHeight + 10;
				addChild(__info);
			}
            __urLoader.removeEventListener(Event.COMPLETE, __userLoaded);
		}
		
		// load traveller trips
		private function __loadTrips(e:Event):void 
		{	
			__url = Bundle.API_URL + "trips_info?token=" + Bundle.TOKEN + "&traveller=" + __traveller.nick;
			__urRequest.url = __url;
			__urLoader.addEventListener(Event.COMPLETE, __onTripsLoaded);
			__urLoader.load(__urRequest);
			
			//__api.loadTravellerTrips(__traveller, __onTripsLoaded);
		}
		
		// traveller trips loaded
		private function __onTripsLoaded(e:Event/*traveller:Traveller*/):void
		{
			var trips_info:XML = XML(__urLoader.data);
			for each (var trip:XML in trips_info.trip) {
				
				var t : Trip = __model.getTripFromXML(trip);
				__traveller.trips.push( t );
				
				if (__traveller.cities[t.city.geonameId]) __traveller.cities[t.city.geonameId]++;
				else __traveller.cities[t.city.geonameId] = 1;
				
			}
			
			__initMap();
			
			// TODO : Load Fellow Travellers
			//__api.loadFellowTravellers(__fellowTravellersLoaded);
			//__traveller = traveller;
		}
		
		// init map with infos
		private function __initMap():void 
		{
			__map.enableDragging();
			__map.enableScrollWheelZoom();
			
			eaze(__loader).killTweens().to(0.5, { y : stage.stageHeight + 20 } ).easing(Back.easeIn)
				.chain(__protector).to(0.5, { alpha:0 } ).onComplete( __removeProtector )
				.chain(__user).to(0.5, { y : 0 } )
				.chain(__info).to(0.5, { y : stage.stageHeight - __info.height } );
			
			__aMarkers = [];
			for each ( var trip : Trip in __traveller.trips ) {
				
				var target : LatLng = new LatLng(trip.city.latitude, trip.city.longitude);
				var lat:Number = trip.city.latitude;
				var lon:Number = trip.city.longitude;
				
				var latOffset:Number = 1;
				var lonOffset:Number = 1;
				
				var indice : int = __traveller.cities[trip.city.geonameId];
				
				var city:Polygon = new Polygon(new CirclePoints(target, indice * 30, 360).circleLatLngs, 
				new PolygonOptions({ 
					strokeStyle: new StrokeStyle({
						color: trip.city.rgb,
						thickness: 2,
						alpha: 1 } ),
					fillStyle : new FillStyle( {
						color:trip.city.rgb,
						alpha: 0.2
						})
					}
				));
				
				__aMarkers.push(city);
			}
			
			__timerCities = new Timer(800, __aMarkers.length);
			__timerCities.addEventListener(TimerEvent.TIMER, __displayCities);
			__timerCities.addEventListener(TimerEvent.TIMER_COMPLETE, __timerComplete);
			__timerCities.start();
			__map.setZoom(4);
		}
		
		private function __displayCities(e:TimerEvent):void 
		{
			var index : int = __timerCities.currentCount - 1;
			__map.panTo(new LatLng(__traveller.trips[index].city.latitude, __traveller.trips[index].city.longitude));
			__map.addOverlay(__aMarkers[index]);
			info(__traveller.trips[index].city.name);
		}
		
		private function __fellowTravellersLoaded( fellows:Array ):void
		{
			__fellows = [];
			for ( var i : int = 0; i < fellows.length; i++ ) 
			{
				var fellow : FellowUI = new FellowUI(fellows[i]);
				fellow.x = 245 + (i * 60);
				fellow.y = - fellow.height - 10;
				fellow.rotationZ = -10;
				addChild(fellow);
				__fellows.push(fellow);
			}
			
			__timerFellows = new Timer(500, fellows.length);
			__timerFellows.addEventListener(TimerEvent.TIMER, __displayFellows);
			__timerFellows.addEventListener(TimerEvent.TIMER_COMPLETE, __timerComplete);
			__timerFellows.start();
		}
		
		private function __timerComplete(e:TimerEvent):void 
		{
			if (__timerFellows) {
				__timerFellows.stop();
				__timerFellows = null;
			}
			if (__timerCities) {
				__timerCities.stop();
				__timerCities = null;
				__map.setZoom(2);
				info(__traveller.currentCity.name);
			}
		}
		
		private function __displayFellows(e:TimerEvent):void 
		{
			eaze(__fellows[__timerFellows.currentCount - 1]).to(0.3, { y : -10 } );
		}
		
		private function __removeProtector():void
		{
			removeChild(__protector);
		}
		
		private function __removeLogin():void
		{
			removeChild(__login);
		}
		
		private function __progressHandler(e:ProgressEvent):void 
		{
			var percent : Number = Math.round(( e.bytesLoaded * 100 ) / e.bytesTotal);
			__loader.setText(percent + "%");
		}
		
		private function __errorHandler(e:Event = null):void 
		{
			FlashConnect.trace("ERROR");
		}
		
		private function info(value:String):void 
		{
			__info.setText(value);
		}
		
		private function __resize(e:Event):void 
		{
			__map.setSize(new Point(stage.stageWidth, stage.stageHeight));
			__login.x = (stage.stageWidth - __login.width) >> 1;
			__login.y = (stage.stageHeight - __login.height) >> 1;
			__protector.height = stage.stageHeight;
			__protector.width = stage.stageWidth;
		}
	}
	
}